package com.wxapp.sale.service.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.wxapp.common.constant.base.IBaseService;
import com.wxapp.common.constant.pojo.vm.ResultVm;
import com.wxapp.common.constant.pojo.vo.UserVo;
import com.wxapp.common.core.annotation.GetCatch;
import com.wxapp.common.util.check.CheckUtil;
import com.wxapp.common.util.condition.ConditionUtil;
import com.wxapp.common.util.copy.CopyUtil;
import com.wxapp.sale.api.pojo.entity.GoodsDO;
import com.wxapp.sale.api.pojo.entity.GoodsSpecDO;
import com.wxapp.sale.api.pojo.entity.GoodsSpecDetailDO;
import com.wxapp.sale.api.pojo.vm.goodsSpec.*;
import com.wxapp.sale.api.pojo.vo.goodsSpec.*;
import com.wxapp.sale.service.mapper.GoodsMapper;
import com.wxapp.sale.service.mapper.GoodsSpecDetailMapper;
import com.wxapp.sale.service.mapper.GoodsSpecMapper;
import com.wxapp.sale.service.service.GoodsSpecService;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

/**
 * @author lgl
 */
@Service
@RequiredArgsConstructor
public class GoodsSpecServiceImpl extends IBaseService implements GoodsSpecService {
    private final GoodsSpecMapper goodsSpecMapper;
    private final GoodsSpecDetailMapper goodsSpecDetailMapper;
    private final GoodsMapper goodsMapper;

    @Override
    @GlobalTransactional(rollbackFor = Exception.class)
    public ResultVm<String> add(UserVo userVo, QGoodSpecAddVo qGoodSpecAddVo) {
        var query = new LambdaQueryWrapper<GoodsSpecDO>();
        query.eq(GoodsSpecDO::getTypeId, qGoodSpecAddVo.getTypeId()).eq(GoodsSpecDO::getName, qGoodSpecAddVo.getName()).eq(GoodsSpecDO::getStatus, true);
        if (goodsSpecMapper.isExist(query)) {
            return error("类型名称已经存在");
        }
        var goodsSpec = CopyUtil.copyObjectNew(qGoodSpecAddVo, GoodsSpecDO::new, (s, r) -> {
            r.setCreateBy(userVo.getId());
            return null;
        });
        goodsSpecMapper.insert(goodsSpec);
        return success("保存类型成功");
    }

    @Override
    @GlobalTransactional(rollbackFor = Exception.class)
    public ResultVm<String> update(UserVo userVo, QGoodSpecUpdateVo qGoodSpecUpdateVo) {
        var goodsSpec = goodsSpecMapper.selectById(qGoodSpecUpdateVo.getId());
        if (CheckUtil.isNullObject(goodsSpec)) {
            return error("类型信息没有找到");
        }
        CopyUtil.copyObject(qGoodSpecUpdateVo, goodsSpec, (s, r) -> {
            r.setUpdateBy(userVo.getId());
            return null;
        });
        goodsSpecMapper.updateById(goodsSpec);
        return success("更新成功");
    }

    @Override
    public ResultVm<String> delete(UserVo userVo, String id) {
        var update = new LambdaUpdateWrapper<GoodsSpecDO>();
        update.eq(GoodsSpecDO::getId, id).eq(GoodsSpecDO::getStatus, true).set(GoodsSpecDO::getStatus, false);
        goodsSpecMapper.update(null, update);
        var goodsSpecDetailUpdate = new LambdaUpdateWrapper<GoodsSpecDetailDO>();
        goodsSpecDetailUpdate.eq(GoodsSpecDetailDO::getSpecId, id).eq(GoodsSpecDetailDO::getStatus, true).set(GoodsSpecDetailDO::getStatus, false);
        goodsSpecDetailMapper.update(null, goodsSpecDetailUpdate);
        return success("删除成功");
    }

    @Override
    @GlobalTransactional(rollbackFor = {Exception.class, RuntimeException.class})
    public ResultVm<String> editDetail(UserVo userVo, String id, List<QGoodSpecDetailUpdateVo> vo) {
        List<String> ids = new ArrayList<>();
        List<GoodsSpecDetailDO> goodsSpecDetails = new ArrayList<>();
        vo.stream().forEach(s -> {
            if (CheckUtil.isNotNullString(s.getId())) {
                ids.add(s.getId());
            } else {
                GoodsSpecDetailDO goodsSpecDetail = new GoodsSpecDetailDO(id, s.getName(), s.getParam());
                goodsSpecDetail.setCreateBy(userVo.getId());
                goodsSpecDetails.add(goodsSpecDetail);
            }
        });
        var query = new LambdaUpdateWrapper<GoodsSpecDetailDO>();
        query.eq(GoodsSpecDetailDO::getStatus, true).eq(GoodsSpecDetailDO::getSpecId, id).notIn(CheckUtil.isNotNullList(ids), GoodsSpecDetailDO::getId, ids).set(GoodsSpecDetailDO::getStatus, false);
        goodsSpecDetailMapper.update(null, query);
        if (!goodsSpecDetails.isEmpty()) {
            goodsSpecDetailMapper.insertBatch(goodsSpecDetails);
        }
        return success("保存成功");
    }

    @Override
    public ResultVm<PGoodSpecDetailVm> detail(String id) {
        var goodsSpec = goodsSpecMapper.selectById(id);
        if (CheckUtil.isNullObject(goodsSpec)) {
            return error("类型信息没有找到");
        }
        return success(CopyUtil.copyObjectNew(goodsSpec, PGoodSpecDetailVm::new, null));
    }

    @Override
    public ResultVm<IPage<PGoodSpecPageVm>> page(QGoodSpecPageVo qGoodSpecPageVo, UserVo userVo) {
        var sCondition = ConditionUtil.getSCondition(GoodsSpecDO::new, qGoodSpecPageVo, null, null, userVo.getId());
        var page = ConditionUtil.getPage(qGoodSpecPageVo, GoodsSpecDO.class);
        var selectPage = goodsSpecMapper.selectPage(page, sCondition);
        var vmPage = CopyUtil.copyPage(selectPage, PGoodSpecPageVm::new, null);
        return success(vmPage);
    }

    @Override
    public ResultVm<List<PGoodSpecDetailListVm>> detailList(String id, UserVo userVo) {
        var query = new LambdaQueryWrapper<GoodsSpecDetailDO>();
        query.eq(GoodsSpecDetailDO::getSpecId, id).eq(GoodsSpecDetailDO::getCreateBy, userVo.getId()).eq(GoodsSpecDetailDO::getStatus, true);
        var specDetails = goodsSpecDetailMapper.selectList(query);
        return success(CopyUtil.copyListNew(specDetails, PGoodSpecDetailListVm::new, null));
    }

    @Override
    public ResultVm<List<PGoodSpecSelectVm>> selectSpec(String name, UserVo userVo) {
        var query = new LambdaQueryWrapper<GoodsSpecDO>();
        query.like(CheckUtil.isNotNullString(name), GoodsSpecDO::getName, name).eq(GoodsSpecDO::getCreateBy, userVo.getId()).eq(GoodsSpecDO::getStatus, true);
        var goodsSpec = goodsSpecMapper.selectList(query);
        if (CheckUtil.isNullList(goodsSpec)) {
            return success(new ArrayList<>());
        }
        return success(CopyUtil.copyListNew(goodsSpec, PGoodSpecSelectVm::new, null));
    }

    @Override
    public ResultVm<List<PGoodSpecSelectVm>> selectSpecDetail(String specId, String name, UserVo userVo) {
        var specDetailQuery = new LambdaQueryWrapper<GoodsSpecDetailDO>();
        specDetailQuery.eq(GoodsSpecDetailDO::getSpecId, specId).like(CheckUtil.isNotNullString(name), GoodsSpecDetailDO::getName, name).eq(GoodsSpecDetailDO::getCreateBy, userVo.getId()).eq(GoodsSpecDetailDO::getStatus, true);
        var specDetails = goodsSpecDetailMapper.selectList(specDetailQuery);
        if (CheckUtil.isNullList(specDetails)) {
            return success(new ArrayList<>());
        }
        return success(CopyUtil.copyListNew(specDetails, PGoodSpecSelectVm::new, null));
    }

    @Override
    @GetCatch(key = "#typeId")
    public ResultVm<List<PGoodsSpecVm>> getListByTypeId(String typeId) {
        var specQuery = new LambdaQueryWrapper<GoodsSpecDO>();
        specQuery.eq(GoodsSpecDO::getTypeId, typeId).eq(GoodsSpecDO::getStatus, true);
        var specs = goodsSpecMapper.selectList(specQuery);
        if (CheckUtil.isNullList(specs)) {
            return success(new ArrayList<>());
        }
        return success(CopyUtil.copyListNew(specs, PGoodsSpecVm::new, null));
    }

    @Override
    @GetCatch(key = "#specId")
    public ResultVm<List<PGoodSpecDetailBaseVm>> getSpecDetailByPid(String specId) {
        var specDetailQuery = new LambdaQueryWrapper<GoodsSpecDetailDO>();
        specDetailQuery.eq(GoodsSpecDetailDO::getSpecId, specId).eq(GoodsSpecDetailDO::getStatus, true);
        var specDetails = goodsSpecDetailMapper.selectList(specDetailQuery);
        if (CheckUtil.isNullList(specDetails)) {
            return success(new ArrayList<>());
        }
        List<String> specDetailIds = specDetails.stream().map(GoodsSpecDetailDO::getId).toList();
        LambdaQueryWrapper<GoodsDO> goodQuery = new LambdaQueryWrapper<>();
        goodQuery.select(GoodsDO::getSpecDetailId).in(GoodsDO::getSpecDetailId, specDetailIds).eq(GoodsDO::getStatus, true);
        List<GoodsDO> goodsDOS = goodsMapper.selectList(goodQuery);
        List<String> goodsIds = goodsDOS.stream().map(GoodsDO::getSpecDetailId).toList();
        var result = CopyUtil.copyListNew(specDetails, PGoodSpecDetailBaseVm::new, (s, r) -> {
            r.setHaveProduct(goodsIds.contains(s.getId()));
            return null;
        });
        return success(result);
    }
}
